home *** CD-ROM | disk | FTP | other *** search
/ Just Call Me Internet / Just Call Me Internet.iso / prog / atari / c / zmdm / zm.c < prev    next >
C/C++ Source or Header  |  1993-06-26  |  14KB  |  694 lines

  1. /*
  2.  *                ACKNOWLEDGEMENTS
  3.  *
  4.  *    ZMDM was derived from rz/sz for Unix  posted by 
  5.  *    Chuck Forsberg (...!tektronix!reed!omen!caf ). We
  6.  *    thank him for his excellent code, and for giving
  7.  *    us permission to use and distribute his code and
  8.  *    documentation.
  9.  *
  10.  *    Atari St version by:
  11.  *        Jwahar Bammi
  12.  *            usenet: cwruecmp!bammi@decvax.UUCP
  13.  *            csnet:  bammi@cwru.edu
  14.  *            arpa:   bammi@cwru.edu
  15.  *            CompuServe: 71515,155
  16.  */
  17.  
  18. /*
  19.  *   Z M . C
  20.  *    ZMODEM protocol primitives
  21.  *    01-15-87  Chuck Forsberg Omen Technology Inc
  22.  *
  23.  * Entry point Functions:
  24.  *    zsbhdr(type, hdr) send binary header
  25.  *    zshhdr(type, hdr) send hex header
  26.  *    zgethdr(hdr, eflag) receive header - binary or hex
  27.  *    zsdata(buf, len, frameend) send data
  28.  *    zrdata(buf, len) receive data
  29.  *    stohdr(pos) store position data in Txhdr
  30.  *    long rclhdr(hdr) recover position offset from header
  31.  */
  32. #include "zmdm.h"
  33. #include "common.h"
  34.  
  35. #ifndef CANFDX
  36. #include "zmodem.h"
  37. #endif
  38.  
  39. #define xsendline(X) sendline(X)
  40.  
  41. static char *frametypes[] = {
  42.     "Carrier Lost",        /* -3 */
  43.     "TIMEOUT",        /* -2 */
  44.     "ERROR",        /* -1 */
  45. #define FTOFFSET 3
  46.     "ZRQINIT",
  47.     "ZRINIT",
  48.     "ZSINIT",
  49.     "ZACK",
  50.     "ZFILE",
  51.     "ZSKIP",
  52.     "ZNAK",
  53.     "ZABORT",
  54.     "ZFIN",
  55.     "ZRPOS",
  56.     "ZDATA",
  57.     "ZEOF",
  58.     "ZFERR",
  59.     "ZCRC",
  60.     "ZCHALLENGE",
  61.     "ZCOMPL",
  62.     "ZCAN",
  63.     "ZFREECNT",
  64.     "ZCOMMAND",
  65.     "ZSTDERR",
  66.     "xxxxx"
  67. #define FRTYPES 22    /* Total number of frame types in this array */
  68.             /*  not including psuedo negative entries */
  69. };
  70.  
  71. /* Send ZMODEM binary header hdr of type type */
  72. zsbhdr(type, hdr)
  73. register char *hdr;
  74. {
  75.     register n;
  76.     register unsigned int crc;
  77.  
  78.     vfile2("zsbhdr: %s %lx", frametypes[type+FTOFFSET], rclhdr(hdr));
  79.     if (type == ZDATA)
  80.         for (n = Znulls; --n >=0; )
  81.             zsendline(0);
  82.  
  83.     xsendline(ZPAD); xsendline(ZDLE);
  84.  
  85.     if (Txfcs32)
  86.         zsbh32(hdr, type);
  87.     else {
  88.         xsendline(ZBIN); zsendline(type); crc = updcrc(type, 0);
  89.  
  90.         for (n=4; --n >= 0;) {
  91.             zsendline(*hdr);
  92.             crc = updcrc((0377& *hdr++), crc);
  93.         }
  94.         crc = updcrc(0,updcrc(0,crc));
  95.         zsendline(crc>>8);
  96.         zsendline(crc);
  97.     }
  98.     if (type != ZDATA)
  99.         flush_modem();
  100. }
  101.  
  102.  
  103. /* Send ZMODEM binary header hdr of type type */
  104. zsbh32(hdr, type)
  105. register char *hdr;
  106. {
  107.     register int n;
  108.     register unsigned long crc;
  109.  
  110.     xsendline(ZBIN32);  zsendline(type);
  111.     crc = 0xFFFFFFFFL; crc = UPDC32(type, crc);
  112. /*    crc = UPDC32(type, 0xFFFFFFFFL); */
  113.  
  114.     for (n=4; --n >= 0;) {
  115.         zsendline(*hdr);
  116.         crc = UPDC32((0377& *hdr++), crc);
  117.     }
  118.     crc = ~crc;
  119.     for (n=4; --n >= 0;) {
  120.         zsendline((unsigned int)(crc&0xFFFF));  crc >>= 8;
  121.     }
  122. }
  123.  
  124. /* Send ZMODEM HEX header hdr of type type */
  125. zshhdr(type, hdr)
  126. register char *hdr;
  127. {
  128.     register int n;
  129.     register unsigned int crc;
  130.  
  131.     vfile2("zshhdr: %s %lx", frametypes[type+FTOFFSET], rclhdr(hdr));
  132.     sendline(ZPAD); sendline(ZPAD); sendline(ZDLE); sendline(ZHEX);
  133.     zputhex(type);
  134.  
  135.     crc = updcrc(type, 0);
  136.     for (n=4; --n >= 0;) {
  137.         zputhex(*hdr); crc = updcrc((0377& *hdr++), crc);
  138.     }
  139.     crc = updcrc(0,updcrc(0,crc));
  140.     zputhex(crc>>8); zputhex(crc);
  141.  
  142.     /* Make it printable on remote machine */
  143.     sendline(015); sendline(012);
  144.     /*
  145.      * Uncork the remote in case a fake XOFF has stopped data flow
  146.      */
  147.     if (type != ZFIN)
  148.         sendline(021);
  149.     flush_modem();
  150. }
  151.  
  152. /*
  153.  * Send binary array buf of length length, with ending ZDLE sequence frameend
  154.  */
  155. zsdata(buf, length, frameend)
  156. register char *buf;
  157. {
  158.     register unsigned int crc;
  159.  
  160.     vfile("zsdata: length=%d end=%x", length, frameend);
  161.     if (Txfcs32)
  162.         zsda32(buf, length, frameend);
  163.     else {
  164.         crc = 0;
  165.         for (;--length >= 0;) {
  166.             zsendline(*buf);
  167.             crc = updcrc((0377& *buf++), crc);
  168.         }
  169.         xsendline(ZDLE); xsendline(frameend);
  170.         crc = updcrc(frameend, crc);
  171.  
  172.         crc = updcrc(0,updcrc(0,crc));
  173.         zsendline(crc>>8); zsendline(crc);
  174.     }
  175.     if (frameend == ZCRCW) {
  176.         xsendline(XON);   flush_modem();
  177.     }
  178. }
  179.  
  180. zsda32(buf, length, frameend)
  181. register char *buf;
  182. {
  183.     register unsigned long crc;
  184.  
  185.     crc = 0xFFFFFFFFL;
  186.     for (;--length >= 0;) {
  187.         zsendline(*buf); crc = UPDC32((0377& *buf++), crc);
  188.     }
  189.     xsendline(ZDLE); xsendline(frameend);
  190.     crc = UPDC32(frameend, crc);
  191.  
  192.     crc = ~crc;
  193.     for (length=4; --length >= 0;) {
  194.         zsendline((unsigned int)(crc&0xFFFF));  crc >>= 8;
  195.     }
  196. }
  197.  
  198. /*
  199.  * Receive array buf of max length with ending ZDLE sequence
  200.  *  and CRC.  Returns the ending character or error code.
  201.  */
  202. zrdata(buf, length)
  203. register char *buf;
  204. {
  205.     register int c;
  206.     register unsigned int crc;
  207.     register int d;
  208.  
  209.     if (Rxframeind == ZBIN32)
  210.         return zrdat32(buf, length);
  211.  
  212.     crc = Rxcount = 0;
  213.     for (;;) {
  214.         if ((c = zdlread()) & ~0377) {
  215. crcfoo:
  216.             switch (c) {
  217.             case GOTCRCE:
  218.             case GOTCRCG:
  219.             case GOTCRCQ:
  220.             case GOTCRCW:
  221.                 crc = updcrc((d=c)&0377, crc);
  222.                 if ((c = zdlread()) & ~0377)
  223.                     goto crcfoo;
  224.                 crc = updcrc(c, crc);
  225.                 if ((c = zdlread()) & ~0377)
  226.                     goto crcfoo;
  227.                 crc = updcrc(c, crc);
  228.                 if (crc & 0xFFFF) {
  229.                     log2("Bad data CRC %x", crc);
  230.                     return ERROR;
  231.                 }
  232.                 vfile("zrdata: cnt = %d ret = %x", Rxcount, d);
  233.                 return d;
  234.             case GOTCAN:
  235.                 log2("ZMODEM: Sender Canceled");
  236.                 return ZCAN;
  237.             case TIMEOUT:
  238.                 log2("ZMODEM data TIMEOUT");
  239.                 return c;
  240.             default:
  241.                 log2("ZMODEM bad data subpacket ret=%x", c);
  242.                 return c;
  243.             }
  244.         }
  245.         if (--length < 0) {
  246.             log2("ZMODEM data subpacket too long");
  247.             return ERROR;
  248.         }
  249.         ++Rxcount;
  250.         *buf++ = c;
  251.         crc = updcrc(c, crc);
  252.         continue;
  253.     }
  254. }
  255. zrdat32(buf, length)
  256. register char *buf;
  257. {
  258.     register int c;
  259.     register unsigned long crc;
  260.     register int d;
  261.  
  262.     crc = 0xFFFFFFFFL;  Rxcount = 0;
  263.     for (;;) {
  264.         if ((c = zdlread()) & ~0377) {
  265. crcfoo:
  266.             switch (c) {
  267.             case GOTCRCE:
  268.             case GOTCRCG:
  269.             case GOTCRCQ:
  270.             case GOTCRCW:
  271.                 crc = UPDC32((d=c)&0377, crc);
  272.                 if ((c = zdlread()) & ~0377)
  273.                     goto crcfoo;
  274.                 crc = UPDC32(c, crc);
  275.                 if ((c = zdlread()) & ~0377)
  276.                     goto crcfoo;
  277.                 crc = UPDC32(c, crc);
  278.                 if ((c = zdlread()) & ~0377)
  279.                     goto crcfoo;
  280.                 crc = UPDC32(c, crc);
  281.                 if ((c = zdlread()) & ~0377)
  282.                     goto crcfoo;
  283.                 crc = UPDC32(c, crc);
  284.                 if (crc != 0xDEBB20E3L) {
  285.                     log2("Bad data CRC");
  286.                     return ERROR;
  287.                 }
  288.                 vfile2("zrdat32: cnt = %ld ret = %x", Rxcount, d);
  289.                 return d;
  290.             case GOTCAN:
  291.                 log2("ZMODEM: Sender Canceled");
  292.                 return ZCAN;
  293.             case TIMEOUT:
  294.                 log2("ZMODEM data TIMEOUT");
  295.                 return c;
  296.             default:
  297.                 log2("ZMODEM bad data subpacket ret");
  298.                 return c;
  299.             }
  300.         }
  301.         if (--length < 0) {
  302.             log2("ZMODEM data subpacket too long");
  303.             return ERROR;
  304.         }
  305.         ++Rxcount;
  306.         *buf++ = c;
  307.         crc = UPDC32(c, crc);
  308.         continue;
  309.     }
  310. }
  311.  
  312.  
  313. /*
  314.  * Read a ZMODEM header to hdr, either binary or hex.
  315.  *  eflag controls local display of non zmodem characters:
  316.  *    0:  no display
  317.  *    1:  display printing characters only
  318.  *    2:  display all non ZMODEM characters
  319.  *  On success, set Zmodem to 1 and return type of header.
  320.  *   Otherwise return negative on error
  321.  */
  322. zgethdr(hdr, eflag)
  323. char *hdr;
  324. {
  325.     register int c, n, cancount;
  326.  
  327.     n = Baudrate;    /* Max characters before start of frame */
  328.     cancount = 5;
  329. again:
  330.     Rxframeind = Rxtype = 0;
  331.     switch (c = noxread7()) {
  332.     case RCDO:
  333.     case TIMEOUT:
  334.         goto fifi;
  335.     case CAN:
  336.         if (--cancount <= 0) {
  337.             c = ZCAN; goto fifi;
  338.         }
  339.     /* **** FALL THRU TO **** */
  340.     default:
  341. agn2:
  342.         if ( --n == 0) {
  343.             log2("ZMODEM Garbage count exceeded");
  344.             return(ERROR);
  345.         }
  346.         if (eflag && ((c &= 0177) & 0140))
  347.             bttyout(c);
  348.         else if (eflag > 1)
  349.             bttyout(c);
  350.         if (c != CAN)
  351.             cancount = 5;
  352.         goto again;
  353.     case ZPAD:        /* This is what we want. */
  354.         break;
  355.     }
  356.     cancount = 5;
  357. splat:
  358.     switch (c = noxread7()) {
  359.     case ZPAD:
  360.         goto splat;
  361.     case RCDO:
  362.     case TIMEOUT:
  363.         goto fifi;
  364.     default:
  365.         goto agn2;
  366.     case ZDLE:        /* This is what we want. */
  367.         break;
  368.     }
  369.  
  370.     switch (c = noxread7()) {
  371.     case RCDO:
  372.     case TIMEOUT:
  373.         goto fifi;
  374.     case ZBIN:
  375.         Rxframeind = ZBIN;
  376.         c =  zrbhdr(hdr);
  377.         break;
  378.     case ZBIN32:
  379.         Rxframeind = ZBIN32;
  380.         c =  zrbhdr32(hdr);
  381.         break;
  382.     case ZHEX:
  383.         Rxframeind = ZHEX;
  384.         c =  zrhhdr(hdr);
  385.         break;
  386.     case CAN:
  387.         if (--cancount <= 0) {
  388.             c = ZCAN; goto fifi;
  389.         }
  390.         goto agn2;
  391.     default:
  392.         goto agn2;
  393.     }
  394.     Rxpos = hdr[ZP3] & 0377;
  395.     Rxpos = (Rxpos<<8) + (hdr[ZP2] & 0377);
  396.     Rxpos = (Rxpos<<8) + (hdr[ZP1] & 0377);
  397.     Rxpos = (Rxpos<<8) + (hdr[ZP0] & 0377);
  398. fifi:
  399.     switch (c) {
  400.     case GOTCAN:
  401.         c = ZCAN;
  402.     /* **** FALL THRU TO **** */
  403.     case ZNAK:
  404.     case ZCAN:
  405.     case ERROR:
  406.     case TIMEOUT:
  407.     case RCDO:
  408.         vfile2("ZMODEM: Got %s %s", frametypes[c+FTOFFSET],
  409.           (c >= 0) ? "header" : "error");
  410.     /* **** FALL THRU TO **** */
  411.     default:
  412.         if (c >= -3 && c <= FRTYPES)
  413.             vfile2("zgethdr: %s %lx", frametypes[c+FTOFFSET], Rxpos);
  414.         else
  415.             vfile2("zgethdr: %ld %lx", (long)c, Rxpos);
  416.     }
  417.     return c;
  418. }
  419.  
  420. /* Receive a binary style header (type and position) */
  421. zrbhdr(hdr)
  422. register char *hdr;
  423. {
  424.     register int c, n;
  425.     register unsigned int crc;
  426.  
  427.     if ((c = zdlread()) & ~0377)
  428.         return c;
  429.     Rxtype = c;
  430.     crc = updcrc(c, 0);
  431.  
  432.     for (n=4; --n >= 0;) {
  433.         if ((c = zdlread()) & ~0377)
  434.             return c;
  435.         crc = updcrc(c, crc);
  436.         *hdr++ = c;
  437.     }
  438.     if ((c = zdlread()) & ~0377)
  439.         return c;
  440.     crc = updcrc(c, crc);
  441.     if ((c = zdlread()) & ~0377)
  442.         return c;
  443.     crc = updcrc(c, crc);
  444.     if (crc & 0xFFFF) {
  445.         log2("Bad Header CRC"); return ERROR;
  446.     }
  447.     Zmodem = 1;
  448.     return Rxtype;
  449. }
  450.  
  451. /* Receive a binary style header (type and position) with 32 bit FCS */
  452. zrbhdr32(hdr)
  453. register char *hdr;
  454. {
  455.     register int c, n;
  456.     register unsigned long crc;
  457.  
  458.     if ((c = zdlread()) & ~0377)
  459.         return c;
  460.     Rxtype = c;
  461.     crc = 0xFFFFFFFFL; crc = UPDC32(c, crc);
  462. /*    crc = UPDC32(c, 0xFFFFFFFFL); */
  463.  
  464.     for (n=4; --n >= 0;) {
  465.         if ((c = zdlread()) & ~0377)
  466.             return c;
  467.         crc = UPDC32(c, crc);
  468.         *hdr++ = c;
  469.     }
  470.     for (n=4; --n >= 0;) {
  471.         if ((c = zdlread()) & ~0377)
  472.             return c;
  473.         crc = UPDC32(c, crc);
  474.     }
  475.     if (crc != 0xDEBB20E3L) {
  476.         log2("Bad Header CRC"); return ERROR;
  477.     }
  478.     Zmodem = 1;
  479.     return Rxtype;
  480. }
  481.  
  482.  
  483. /* Receive a hex style header (type and position) */
  484. zrhhdr(hdr)
  485. char *hdr;
  486. {
  487.     register int c;
  488.     register unsigned int crc;
  489.     register int n;
  490.  
  491.     if ((c = zgethex()) < 0)
  492.         return c;
  493.     Rxtype = c;
  494.     crc = updcrc(c, 0);
  495.  
  496.     for (n=4; --n >= 0;) {
  497.         if ((c = zgethex()) < 0)
  498.             return c;
  499.         crc = updcrc(c, crc);
  500.         *hdr++ = c;
  501.     }
  502.     if ((c = zgethex()) < 0)
  503.         return c;
  504.     crc = updcrc(c, crc);
  505.     if ((c = zgethex()) < 0)
  506.         return c;
  507.     crc = updcrc(c, crc);
  508.     if (crc & 0xFFFF) {
  509.         log2("Bad Header CRC"); return ERROR;
  510.     }
  511.     if (readline(1) == '\r')    /* Throw away possible cr/lf */
  512.         readline(1);
  513.     Zmodem = 1; return Rxtype;
  514. }
  515.  
  516. /* Send a byte as two hex digits */
  517. zputhex(c)
  518. register c;
  519. {
  520.     static char    digits[]    = "0123456789abcdef";
  521.  
  522.     if (Verbose>4)
  523.         vfile("zputhex: %x", c);
  524.     sendline(digits[(c&0xF0)>>4]);
  525.     sendline(digits[(c)&0xF]);
  526. }
  527.  
  528. /*
  529.  * Send character c with ZMODEM escape sequence encoding.
  530.  *  Escape XON, XOFF. Escape CR following @ (Telenet net escape)
  531.  */
  532. zsendline(c)
  533. register c;
  534. {
  535.     static lastsent;
  536.  
  537.     switch (c & 0377) {
  538.     case ZDLE:
  539.         xsendline(ZDLE);
  540.         xsendline (lastsent = (c ^= 0100));
  541.         break;
  542.     case 015:
  543.     case 0215:
  544.         if ((lastsent & 0177) != '@')
  545.             goto sendit;
  546.     /* **** FALL THRU TO **** */
  547.     case 020:
  548.     case 021:
  549.     case 023:
  550.     case 0220:
  551.     case 0221:
  552.     case 0223:
  553.     if(SendType)
  554.     {
  555.         if (Zctlesc<0)
  556.             goto sendit;
  557.     }
  558.         
  559.         xsendline(ZDLE);
  560.         c ^= 0100;
  561. sendit:
  562.         xsendline(lastsent = c);
  563.         break;
  564.     default:
  565.         if(SendType)
  566.         {
  567.             if (Zctlesc>0 && ! (c & 0140)) {
  568.                 xsendline(ZDLE);
  569.                 c ^= 0100;
  570.             }
  571.         }
  572.         
  573.         xsendline(lastsent = c);
  574.     }
  575. }
  576.  
  577. /* Decode two lower case hex digits into an 8 bit byte value */
  578. zgethex()
  579. {
  580.     register int c;
  581.  
  582.     c = zgeth1();
  583.     if (Verbose>4)
  584.         vfile("zgethex: %x", c);
  585.     return c;
  586. }
  587. zgeth1()
  588. {
  589.     register int c, n;
  590.  
  591.     if ((c = noxread7()) < 0)
  592.         return c;
  593.     n = c - '0';
  594.     if (n > 9)
  595.         n -= ('a' - ':');
  596.     if (n & ~0xF)
  597.         return ERROR;
  598.     if ((c = noxread7()) < 0)
  599.         return c;
  600.     c -= '0';
  601.     if (c > 9)
  602.         c -= ('a' - ':');
  603.     if (c & ~0xF)
  604.         return ERROR;
  605.     c += (n<<4);
  606.     return c;
  607. }
  608.  
  609. /*
  610.  * Read a byte, checking for ZMODEM escape encoding
  611.  *  including CAN*5 which represents a quick abort
  612.  */
  613. zdlread()
  614. {
  615.     register int c;
  616.  
  617.     if ((c = readline(Rxtimeout)) != ZDLE)
  618.         return c;
  619.     if ((c = readline(Rxtimeout)) < 0)
  620.         return c;
  621.     if (c == CAN && (c = readline(Rxtimeout)) < 0)
  622.         return c;
  623.     if (c == CAN && (c = readline(Rxtimeout)) < 0)
  624.         return c;
  625.     if (c == CAN && (c = readline(Rxtimeout)) < 0)
  626.         return c;
  627.     switch (c) {
  628.     case CAN:
  629.         return GOTCAN;
  630.     case ZCRCE:
  631.     case ZCRCG:
  632.     case ZCRCQ:
  633.     case ZCRCW:
  634.         return (c | GOTOR);
  635.     case ZRUB0:
  636.         return 0177;
  637.     case ZRUB1:
  638.         return 0377;
  639.     default:
  640.         if ((c & 0140) ==  0100)
  641.             return (c ^ 0100);
  642.         break;
  643.     }
  644.     log2("Got bad ZMODEM escape sequence %x", c);
  645.     return ERROR;
  646. }
  647.  
  648. /*
  649.  * Read a character from the modem line with timeout.
  650.  *  Eat parity, XON and XOFF characters.
  651.  */
  652. noxread7()
  653. {
  654.     register int c;
  655.  
  656.     for (;;) {
  657.         if ((c = readline(Rxtimeout)) < 0)
  658.             return c;
  659.         switch (c &= 0177) {
  660.         case XON:
  661.         case XOFF:
  662.             continue;
  663.         default:
  664.             return c;
  665.         }
  666.     }
  667. }
  668.  
  669. /* Store long integer pos in Txhdr */
  670. stohdr(pos)
  671. long pos;
  672. {
  673.     Txhdr[ZP0] = pos;
  674.     Txhdr[ZP1] = pos>>8;
  675.     Txhdr[ZP2] = pos>>16;
  676.     Txhdr[ZP3] = pos>>24;
  677. }
  678.  
  679. /* Recover a long integer from a header */
  680. long
  681. rclhdr(hdr)
  682. register char *hdr;
  683. {
  684.     register long l;
  685.  
  686.     l = (hdr[ZP3] & 0377);
  687.     l = (l << 8) | (hdr[ZP2] & 0377);
  688.     l = (l << 8) | (hdr[ZP1] & 0377);
  689.     l = (l << 8) | (hdr[ZP0] & 0377);
  690.     return l;
  691. }
  692.  
  693. /** EOF **/
  694.